﻿// <copyright file="DateTimeExtensions.cs" company="DotNetLib">
//
// .netlib: http://www.codeplex.com/DotNetLib
//
// This code is released under the New BSD License.
// A copy of this license is available at:
// http://www.codeplex.com/DotNetLib/license
//
// </copyright>

namespace DotNetLib
{
  using System;

  /// <summary>
  /// Extension methods for a <see cref="DateTime"/>.
  /// </summary>
  public static class DateTimeExtensions
  {
    /// <summary>
    /// Obsolete, use IsWeekendDay.
    /// </summary>
    /// <param name="dateTime">Obsolete, use IsWeekendDay.</param>
    /// <returns>Obsolete, use IsWeekendDay.</returns>
    [Obsolete("Renamed to IsWeekendDay", true)]
    public static bool IsWeekend(this DateTime dateTime)
    {
      throw new NotSupportedException();
    }

    /// <summary>
    /// Indicates whether the specified <see cref="DateTime"/> is on a weekend day.
    /// </summary>
    /// <param name="dateTime">The <see cref="DateTime"/> to check.</param>
    /// <returns><b>True</b> if the day represented is a weekend day; <b>false</b> otherwise.</returns>
    public static bool IsWeekendDay(this DateTime dateTime)
    {
      return dateTime.DayOfWeek == DayOfWeek.Saturday || dateTime.DayOfWeek == DayOfWeek.Sunday;
    }

    /// <summary>
    /// Indicates whether the specified <see cref="DateTime"/> occurs on a week day.
    /// </summary>
    /// <param name="dateTime">The <see cref="DateTime"/> to check.</param>
    /// <returns><b>True</b> if the day represented is a week day; <b>false</b> otherwise.</returns>
    public static bool IsWeekday(this DateTime dateTime)
    {
      return !IsWeekendDay(dateTime);
    }

    /// <summary>
    /// Advances the day to fall on the next weekend day.
    /// </summary>
    /// <param name="dateTime">The <see cref="DateTime"/> to advance.</param>
    /// <returns>A new instance of <see cref="DateTime"/> that falls on the next weekend day.  Time units less than a day are maintained.</returns>
    public static DateTime NextWeekendDay(this DateTime dateTime)
    {
      switch (dateTime.DayOfWeek)
      {
        case DayOfWeek.Friday:
        case DayOfWeek.Saturday:
          return dateTime.AddDays(1);
        case DayOfWeek.Sunday:
          return dateTime.AddDays(6);
        case DayOfWeek.Monday:
          return dateTime.AddDays(5);
        case DayOfWeek.Tuesday:
          return dateTime.AddDays(4);
        case DayOfWeek.Wednesday:
          return dateTime.AddDays(3);
        case DayOfWeek.Thursday:
          return dateTime.AddDays(2);
        default:
          throw new InvalidOperationException();
      }
    }

    /// <summary>
    /// Advances the day to fall on the next weekday.
    /// </summary>
    /// <param name="dateTime">The <see cref="DateTime"/> to advance.</param>
    /// <returns>A new instance of <see cref="DateTime"/> that falls on the next weekday.  Time units less than a day are maintained.</returns>
    public static DateTime NextWeekday(this DateTime dateTime)
    {
      switch (dateTime.DayOfWeek)
      {
        case DayOfWeek.Sunday:
        case DayOfWeek.Monday:
        case DayOfWeek.Tuesday:
        case DayOfWeek.Wednesday:
        case DayOfWeek.Thursday:
          return dateTime.AddDays(1);
        case DayOfWeek.Friday:
          return dateTime.AddDays(3);
        case DayOfWeek.Saturday:
          return dateTime.AddDays(2);
        default:
          throw new InvalidOperationException();
      }
    }
  }
}
